package grupo1.fotomultas.Fotomultas;

import grupo1.fotomultas.Fotomultas.Infracciones.HomeInfracciones;
import grupo1.fotomultas.Fotomultas.Infracciones.Infraccion;

import java.util.List;
import java.util.Set;

// COMMENT En general, no pusieron muchos javadoc.
// Lo marco aca porque aca es donde mas tiempo estuve tratando de entender, pero vale para
// el resto del tp.
public class OrganismoDeTransito {

	private InfraccionUpdater updater;
	private ReconocedorDePatentes reconocedor;
	private static OrganismoDeTransito instance = null;
	
	public static OrganismoDeTransito instance() {
		if (instance == null)
			instance = new OrganismoDeTransito(new DetectorDePatentesFailed(), new InfraccionUpdater());
		
		return instance;
	}
	
	private OrganismoDeTransito(ReconocedorDePatentes definirReconocedor, InfraccionUpdater sistemaUpdater) {
		this.reconocedor = definirReconocedor;
		this.updater=sistemaUpdater;
	}

	public void procesarCaptura(Captura unaCaptura) {
	
		try {
			Vehiculo unVehiculo = reconocedor.obtenerVehiculoAPartirDeCaptura(unaCaptura);
			unVehiculo.agregarInfraccion(unaCaptura.getInfraccion());
			}
			catch (CapturaErrorExeption sme) {
				// lo agrego a las infracciones pendientes que no se pudieron procesar automaticamente
				this.agregarAInfraccionesPendientes(unaCaptura);
			}
			
		return;
	}

	private void agregarAInfraccionesPendientes(Captura captura) {
		HomeCapturas.instance().agregarCapturaPendiente(captura);
	}

	public void procesarInfraccionManualmente(Captura captura, String patenteAsignada) {
		if (HomeCapturas.instance().getCapturasPendientes().contains(captura)){
			//Busco la infraccion si la tengo pendiente proceso
			Vehiculo vehiculoEnInfraccion = HomeVehiculos.Instance().obtenerUnVehiculo(patenteAsignada);
			vehiculoEnInfraccion.agregarInfraccion(captura.getInfraccion());
			// si proceso correctamente remuevo
			HomeCapturas.instance().removerCapturaPendiente(captura);
			
			return;
		}
		throw new ProcesarInfraccionManualmenteExeption("La infraccion no se encuentra pendiente de procesar");
		
		// COMMENT Sugerencia, esta bien, pero en general, para evitarme el return, lo que yo hago es:
		// if(!this.infraccionesPendientes.contains(unaInfraccion)) {
		//      throw new ProcesarInfraccionManualmenteExeption("La infraccion no se encuentra pendiente de procesar");
		// }
		// y aca pongo el resto del código
		// (es solo una alternativa algortmica)
	}

	public void setReconocedor(ReconocedorDePatentes reconocedor) {
		this.reconocedor = reconocedor;
	}

	public ReconocedorDePatentes getReconocedor() {
		return reconocedor;
	}


	public List<Captura> getInfraccionesPendientes() {
		return HomeCapturas.instance().getCapturasPendientes();
	}
	
	// aca empieza el punto 1 del la segunda parte
	public void actualizarEstadoDeInfracciones(){
		this.pagarInfracciones();
		this.actualizarInfraccionesPorVencimiento();
		this.actualizarInfraccionesPerdonadas();
		this.actualizarCategorias();
	}

	public void actualizarCategorias() {
		for(Vehiculo vehiculo : HomeVehiculos.Instance().obtenerVehiculos()){
			vehiculo.verificarCategoriasExistentes();
		}
		
	}

	private void actualizarInfraccionesPorVencimiento() {
		for (Infraccion unaInfraccion : HomeInfracciones.Instance().getInfraccionesPendientesDePago()) {
			unaInfraccion.verificarVencimiento();
		}
		
	}

	private void actualizarInfraccionesPerdonadas() {
		Set<Vehiculo> vehiculos = HomeVehiculos.Instance().obtenerVehiculos();
		for (Vehiculo vehiculo : vehiculos) {
			vehiculo.verificarInfraccionesPerdonadas();
		}
		
	}
	
	private void pagarInfracciones() {
		Set<Infraccion> infraccionesPagas = updater.obtenerInfraccionesPagas();
		for (Infraccion infraccionPaga : infraccionesPagas) {
			infraccionPaga.pagar();
			}
	}



	public void setUpdater(InfraccionUpdater updater) {
		this.updater = updater;
	}

	public InfraccionUpdater getUpdater() {
		return updater;
	}

}
